package com.yan.design.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yan.design.pojo.Po;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.function.Function;

/**
 * 集合工具类
 *
 * @author shengren.yan
 * @create 2022-07-12
 */
public class CollectionUtil extends CollectionUtils {

	/**
	 * 检查数组是否包含指定的元素
	 *
	 * @param array   数组
	 * @param element 指定的元素
	 * @return 布尔值 ： true 包含 false 不包含
	 */
	public static <T> boolean arrayContains(@Nullable T[] array, final T element) {
		if (array == null) {
			return false;
		}
		return Arrays.stream(array).anyMatch(x -> ObjectUtils.nullSafeEquals(x, element));
	}

	/**
	 * 去除数组中重复的数据
	 *
	 * @param arr 数组
	 * @return 数组
	 */
	public static String[] removeDuplication(String[] arr) {
		Set<String> set = new HashSet<String>();
		if (null != arr && arr.length > 0) {
			set.addAll(Arrays.asList(arr));
		}
		String[] strArr = set.toArray(new String[set.size()]);
		return strArr;
	}

	/**
	 * 对象是否为数组对象
	 *
	 * @param obj 对象
	 * @return 布尔值 ： true 是 false 否
	 */
	public static boolean isArray(Object obj) {
		if (null == obj) {
			return false;
		}
		return obj.getClass().isArray();
	}


	/**
	 * 复制属性列表
	 *
	 * @param sources 来源
	 * @param target  目标
	 */
	public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) {
		List<T> list = new ArrayList<>(sources.size());
		for (S source : sources) {
			T t = target.get();
			org.springframework.beans.BeanUtils.copyProperties(source, t);
			list.add(t);
		}
		return list;
	}


	/**
	 * 判断元素不为空
	 * @param obj object
	 * @return boolean
	 */
	public static boolean isNotEmptyObj(@Nullable Object obj) {
		return !ObjectUtils.isEmpty(obj);
	}


	/**
	 *  判断集合是否不为空：
	 *
	 * @return 布尔值 ： true 是 false 否
	 */
	public static boolean isNotEmpty(@Nullable Collection<?> coll) {
		return !CollectionUtils.isEmpty(coll);
	}


	/**
	 * 判断 Map 是否不为空：
	 *
	 * @return 布尔值 ： true 是 false 否
	 */
	public static boolean isNotEmpty(@Nullable Map<?, ?> map) {
		return !CollectionUtils.isEmpty(map);
	}


	/**
	 *  Map转对象
	 *  	注意：BigDecimal、数值类型可能丢精度
	 *  		  返回的key实体的成员变量，value值
	 *
	 * @return Map
	 * @throws IllegalAccessException 如果实例化 JavaBean 失败
	 * @throws InvocationTargetException 如果调用属性的 setter 方法失败
	 */
	public static <T> Map<String, String> toEntity( final T x) {
		try {
			return BeanUtils.describe(x);
		} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
//			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	// Map转对象
	public static <T> Map<String, Object> toEntity2(T bean) {
		Map<String, Object> map = new HashMap<>();
		if (bean != null) {
			BeanMap beanMap = BeanMap.create(bean);
			for (Object key : beanMap.keySet()) {
				map.put(key.toString(), beanMap.get(key));
			}
		}
		return map;
	}


	/**
	 *  对象转Map
	 *  	注意：BigDecimal、数值类型可能丢精度
	 *
	 * @return 实体对象
	 */
	public static <T> T toMap(Map<String, ? extends Object> map, Class<T> clazz) {
		try {
			T bean = clazz.newInstance();
			BeanUtils.populate(bean, map);
			return bean;
		} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
			throw new RuntimeException(e);
		}
	}


	/**
	 * list<JavaBean> 转 List<Map<String, Object>>
	 *
	 * @param  objList list集合
	 * @param  <T> 实体对象
	 * @return List<Map<String, Object>>
	 */
	public static <T> List<Map<String, Object>> toListMap(List<T> objList) {
		return objList.stream().map(new Function<T, Map<String, Object>>() {
			@Override
			public Map<String, Object> apply(T t) {
				Map<String, Object> map = new HashMap<>();
				BeanMap beanMap = BeanMap.create(t);
				for (Object key : beanMap.keySet()) {
					map.put(key.toString(), beanMap.get(key));
				}
				return map;
			}
		}).collect(Collectors.toList());
	}


	/**
	 *  获取Map里的所有的key
	 *
	 * @return set集合
	 */
	public static Set<String> getMapKeys(Map<String, ? extends Object> map) {
		return map.keySet();
	}

	/**
	 *  获取Map里的所有的value
	 *
	 * @return set集合
	 */
	public static List<Object> getMapValues(Map<String, ? extends Object> map) {
//		List<Object> objects = new ArrayList<>(map.values());
//		Collections.reverse(objects); // 颠倒排序
		return new ArrayList<>(map.values());
	}

	/**
	 *  获取Map里的所有的key和value
	 *
	 * @return set集合
	 */
	public static Map<String, Object> getMapKV(Map<String, Object> map) {
		List<String> keys = new ArrayList<>();
		List<Object> valuse = new ArrayList<>();
		for (Map.Entry<String, Object> e : map.entrySet()) {
			keys.add(e.getKey());
			valuse.add(e.getValue());
		}
		map.clear();
		map.put("keys",keys);
		map.put("valuse",valuse);
		return map;
	}


	/**
	 *  获取Map里 - 是否存在key
	 *
	 * @return set集合
	 */
	public static Boolean containsKey(Map<String, Object> map, String key) {
		return map.containsKey(key);
	}


	/**
	 * 两个集合取交集
	 *
	 * @param listA 集合A
	 * @param listB 集合B
	 * @param tClass JavaBean
	 * @return 交集
	 * 使用：List<String> arrayList = listIntersection(list,list2,String.class);
	 */
	public static <T> List<T> listIntersection(List<T> listA, List<T> listB, Class<T> tClass) {
		Collection collection = org.apache.commons.collections4.CollectionUtils.retainAll(listA, listB);
		return new ArrayList<>(collection);
	}


	/**
	 * 两个集合取并集
	 *
	 * @param listA 集合A
	 * @param listB 集合B
	 * @param tClass JavaBean
	 * @return 交集
	 * 使用：List<String> arrayList = listUnion(list,list2,String.class);
	 */
	public static <T> List<T> listUnion(List<T> listA, List<T> listB, Class<T> tClass) {
		Collection collection = org.apache.commons.collections4.CollectionUtils.union(listA, listB);
		return new ArrayList<>(collection);
	}


	/**
	 * 两个集合取差集
	 *
	 * @param listA 集合A
	 * @param listB 集合B
	 * @param tClass JavaBean
	 * @return 交集
	 * 使用：List<String> arrayList = listSubtract(list,list2,String.class);
	 */
	public static <T> List<T> listSubtract(List<T> listA, List<T> listB, Class<T> tClass) {
		Collection collection = org.apache.commons.collections4.CollectionUtils.subtract(listA, listB);
		return new ArrayList<>(collection);
	}

	/**
	 * 根据某个元素，去重返回一个集合
	 * putIfAbsent() 方法是
	 *    如果 key对应的value值不存在, key value 添加到 map 中,并返回 null
	 *    如果 key对应的value值已存在, key value 不再添加到 map 中, 并返回原 value
	 *
	 * 使用：list.stream().filter(distinctByVariable(Po::getAge)).collect(Collectors.toList());
	 * 根据多个元素，去重返回一个集合
	 *  list = list.stream()
	 * 		       .collect(Collectors.collectingAndThen(
	 * 						Collectors.toCollection(() -> new TreeSet<>(
	 * 								Comparator.comparing(p -> p.getUsername() + ";" + p.getAge()))
	 * 						), ArrayList::new));
	 */
	public static <T> Predicate<T> distinctByVariable(Function<? super T, ?> keyExtractor) {
		HashMap<Object, Boolean> map = new HashMap<>();
		return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
	}



	public static void main(String[] args) throws Exception{

//		List<String> list = Arrays.asList("a", "b", "c");
//		List<String> lists = Arrays.asList("a", "d", "c");

//		List<Po> list = new ArrayList<>();
//		Po po1 = new Po("a1",11,1);
//		Po po2 = new Po("a2",12,1);
//		Po po3 = new Po("a3",13,2);
//		Po po4 = new Po("a4",14,2);
//		Po po5 = new Po("a5",14,1);
//		Po po6 = new Po("a5",15,1);
////		list.add(po1);
////		list.add(po2);
////		list.add(po3);
////
//		List<Po> list2 = new ArrayList<>();
//		list2.add(po1);
//		list2.add(po2);
//		list2.add(po4);
//		list2.add(po5);
//		list2.add(po6);


		// json字符串转成实体
		String str = "[{\"username\":\"a\",\"age\":12,\"bus\":1}]";
		Po po = JSONObject.parseObject(str, Po.class);
		System.out.println(po);

		// json字符串转集合
		List<Po> tList= JSON.parseArray(str,Po.class);
		System.out.println(tList);
	}

}

//  数组转list
//	Integer[] array2 = {1, 2, 3};
//	方式1：
//	List<Integer> integers = Arrays.asList(array2);
//	方式2：
//	List<String> resultList = new ArrayList<>(array2.length);
//	Collections.addAll(resultList,array2);
//	方式3：
//	List<String> resultList = List.of(array);
//  List转数组
//	Integer[] integers1 = integers.stream().toArray(Integer[]::new);
//  字符串转list
//	String str = "a,2,3";
//	List<String> list = Arrays.asList(StringUtils.split(str));
//	str = StringUtils.join(list);
//  boolean contains = list.contains("2"); 包含
//  实体转实体  - BeanUtils.copyProperties();
//  Po monMeter = monmeterRepository.findById(pojo.getMonMeterId()).orElse(null);
//
//  创建一个  Optional
//  Optional<Po> user1 = Optional.of(new Po());
//  List<String> lists = null;
//	lists = Optional.ofNullable(lists).orElse(new ArrayList());
//  lists.forEach(x -> System.out.println(x));
//  判断是否包含值  true 有值  false 没有值
//  if (user3.isPresent()) {
//		System.out.println("判断是否包含值");
//		ystem.out.println(user3.get());
//	}

// https://blog.csdn.net/qq_20957669/article/details/96326485


